# @rspress/plugin-preview <SourceCode href="https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-preview" />

import { SourceCode, PackageManagerTabs } from '@rspress/core/theme';

Used to preview components in the code block of md(x) files.

## Installation

<PackageManagerTabs command="add @rspress/plugin-preview -D" />

## Usage

### Register

First, write the following config in the config file:

```ts title="rspress.config.ts"
import { defineConfig } from '@rspress/core';
import { pluginPreview } from '@rspress/plugin-preview';

export default defineConfig({
  plugins: [pluginPreview()],
});
```

:::warning Note

This plugin will set `markdown.mdxRs` to `false`. In the future, the Rspress team will port this plugin to the Rust version of the compiler.

:::

### Internal components

The component code of internal components is declared in the mdx file. You can declare the following code block in the mdx file:

````md
```tsx
function App() {
  return <div>Hello World</div>;
}

export default App;
```
````

It's worth noting that you need to export the component as default, and Rspress will automatically render this component.

But if you want to keep the style of the code block instead of rendering it as a component, you can add the `pure` identifier to specify, the usage is as follows:

````md
```tsx pure
function App() {
  return <div>Hello World</div>;
}
export default App;
```
````

If you have set `defaultRenderMode` to `'pure'`, Rspress will not render this component by default, but instead display it as a code block. If you want to render a code block as a component in this situation, you can do add the `preview` identifier to specify, the usage is as follows:

````md
```tsx preview
function App() {
  return <div>Hello World</div>;
}
export default App;
```
````

:::tip Tip
Make sure the document ends with `.mdx`.
:::

### External components

In addition to writing component code in the code block of the mdx file, you can also write component code in an external file and then import it in the mdx file through the meta tag of `file="./filename"`. For example

````md title="example.mdx"
```tsx file="./Demo.tsx"

```
````

```tsx title="Demo.tsx"
export default function App() {
  return <div>Hello World</div>;
}
```

External components also need to export the component as default. Through the src attribute of the code tag, you can specify the path of the external component. This plugin supports both relative paths and alias paths(alias).

For some more complex components, this way of using external components will be more convenient.

## Options

This plugin accepts an object parameter of the following type:

```ts
interface PreviewOptions {
  previewMode?: 'internal' | 'iframe';
  iframeOptions?: IframeOptions;
  defaultRenderMode?: 'pure' | 'preview';
}

interface IframeOptions {
  framework?: 'react' | 'solid';
  position?: 'fixed' | 'follow';
  devPort?: number;
}
```

### defaultRenderMode

The default mode of rendering internal code blocks that do not have the `pure` or `preview` identifiers declared by users, defaulting to `preview`.

- `pure`: render as regular code block
- `preview`: render as component

### previewMode

The `previewMode` parameter is used to specify whether the preview mode is internal, defaulting to `internal`. The default mode display effect is as follows:

![](https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/rspress/demo-preview-pc.jpeg)

You can also set it for each individual code block:

````md title="example.mdx"
```tsx iframe
function App() {
  return <div>Hello World</div>;
}
export default App;
```
````

````md title="example.mdx"
```tsx file="./demo.tsx" iframe

```
````

If previewMode is `iframe`, you can use the following configuration for the iframe:

### iframeOptions.position

In iframe preview mode, you can use the `iframeOptions.position` parameter to determine the position of the preview area iframe, whether it follows page scrolling (`follow` mode) or is fixed on the page (`fixed` mode), defaulting to `follow`.

The effect of `follow` mode is as follows:

![](https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/rspress/demo-preview-mobile-follow.png)

The effect of `fixed` mode is as follows:

![](https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/rspress/demo-preview-mobile-fixed.png)

### iframeOptions.framework

In iframe preview mode, you can choose the rendering framework, currently supports `react` and `solid`.

### iframeOptions.devPort

In the iframe preview mode, you can configure the dev server port of the preview component.

### iframeOptions.builderConfig

Configure the buildConfig of the iframe, such as adding some global code.

### iframeOptions.customEntry

Configure custom entry to support other `Web` frameworks, such as `Vue`.

Use customEntry only `iframeOptions.position = follow`.

```ts
import { defineConfig } from '@rspress/core';
import { pluginPreview } from '@rspress/plugin-preview';
import { pluginVue } from '@rsbuild/plugin-vue';

export default defineConfig({
  // ...
  plugins: [
    pluginPreview({
      previewMode: 'iframe',
      previewLanguages: ['vue'],
      iframeOptions: {
        position: 'follow',
        customEntry: ({ entryCssPath, demoPath }) => {
          return `
          import { createApp } from 'vue';
          import App from ${JSON.stringify(demoPath)};
          import ${JSON.stringify(entryCssPath)};
          createApp(App).mount('#root');
          `;
        },
        builderConfig: {
          plugins: [pluginVue()],
        },
      },
    }),
  ],
});
```

### deprecated: isMobile

From v1.12.0, please use [previewMode](#previewmode) instead.

### deprecated: iframePosition

From v1.12.0, please use [iframeOptions.position](#iframeoptionsposition) instead.

### previewLanguages

- Type: `string[]`
- Default: `['jsx', 'tsx']`

The code languages that support preview, by default jsx and tsx codes are supported. If you need to support other formats of code, such as json/yaml, you can use it in conjunction with the `previewCodeTransform` configuration below.

### previewCodeTransform

- Type: `(codeInfo: { language: string; code: string }) => string`
- default: `({ code }) => code`

Customize the transformation of the code before previewing. For example, if you want to render a piece of JSON Schema through custom transformation logic:

```json
{
  "type": "div",
  "children": "Render from JSON"
}
```

You can make the following configuration:

```ts
pluginPreview({
  // Note to add the default jsx and tsx
  previewLanguages: ['jsx', 'tsx', 'json'],
  previewCodeTransform(codeInfo) {
    if (codeInfo.language === 'json') {
      return `
import React from 'react';

const json = ${codeInfo.code};

export default function() {
return React.createElement(json.type, null, json.children);
}
`;
    } else {
      return codeInfo.code;
    }
  },
});
```

In this way, the component code after custom logic transformation will be rendered in the end.

:::warning Note

The `previewLanguages` and `previewCodeTransform` configurations only take effect for internal components, that is, they take effect for code blocks declared in mdx files, but they do not take effect for external files declared in `code` tags!

:::
